// ----------------------------------------------------------------------------
// diabindException.h
// DIA Symbol
// ----------------------------------------------------------------------------

#pragma once

// ----------------------------------------------------------------------------

#include "diabindException.h"

// ----------------------------------------------------------------------------

namespace diabind
{

// ----------------------------------------------------------------------------

interface ISymbol;
typedef boost::shared_ptr< ISymbol > CSymbolPtr;

interface IEnumSymbols;
typedef boost::shared_ptr< IEnumSymbols > CEnumSymbolsPtr;

// ----------------------------------------------------------------------------

interface ISymbol
{
    virtual ~ISymbol() {}

    virtual CEnumSymbolsPtr findChildren(
        DWORD symtag,
        std::wstring name,
        DWORD compareFlags
    ) = 0;
    virtual DWORD get_symTag() = 0;
    virtual std::wstring get_name() = 0;
    virtual std::wstring get_undecoratedNameEx(DWORD undecorateOptions) = 0;
    virtual DWORD get_symIndexId() = 0;
    virtual CSymbolPtr get_lexicalParent() = 0;
    virtual CSymbolPtr get_classParent() = 0;
    virtual CSymbolPtr get_type() = 0;
    virtual DWORD get_dataKind() = 0;
    virtual DWORD get_locationType() = 0;
    virtual DWORD get_addressSection() = 0;
    virtual DWORD get_addressOffset() = 0;
    virtual DWORD get_relativeVirtualAddress() = 0;
    virtual ULONGLONG get_virtualAddress() = 0;
    virtual DWORD get_registerId() = 0;
    virtual LONG get_offset() = 0;
    virtual ULONGLONG get_length() = 0;
    virtual DWORD get_slot() = 0;
    virtual bool get_volatileType() = 0;
    virtual bool get_constType() = 0;
    virtual bool get_unalignedType() = 0;
    virtual DWORD get_access() = 0;
    virtual std::wstring get_libraryName() = 0;
    virtual DWORD get_platform() = 0;
    virtual DWORD get_language() = 0;
    virtual bool get_editAndContinueEnabled() = 0;
    virtual DWORD get_frontEndMajor() = 0;
    virtual DWORD get_frontEndMinor() = 0;
    virtual DWORD get_frontEndBuild() = 0;
    virtual DWORD get_backEndMajor() = 0;
    virtual DWORD get_backEndMinor() = 0;
    virtual DWORD get_backEndBuild() = 0;
    virtual std::wstring get_sourceFileName() = 0;
    virtual DWORD get_thunkOrdinal() = 0;
    virtual LONG get_thisAdjust() = 0;
    virtual DWORD get_virtualBaseOffset() = 0;
    virtual bool get_virtual() = 0;
    virtual bool get_intro() = 0;
    virtual bool get_pure() = 0;
    virtual python::object get_value() = 0;
    virtual DWORD get_callingConvention() = 0;
    virtual DWORD get_baseType() = 0;
    virtual DWORD get_token() = 0;
    virtual DWORD get_timeStamp() = 0;
    virtual std::wstring get_guid() = 0;
    virtual std::wstring get_symbolsFileName() = 0;
    virtual bool get_reference() = 0;
    virtual DWORD get_count() = 0;
    virtual DWORD get_bitPosition() = 0;
    virtual CSymbolPtr get_arrayIndexType() = 0;
    virtual bool get_packed() = 0;
    virtual bool get_constructor() = 0;
    virtual bool get_overloadedOperator() = 0;
    virtual bool get_nested() = 0;
    virtual bool get_hasNestedTypes() = 0;
    virtual bool get_hasAssignmentOperator() = 0;
    virtual bool get_hasCastOperator() = 0;
    virtual bool get_scoped() = 0;
    virtual bool get_virtualBaseClass() = 0;
    virtual bool get_indirectVirtualBaseClass() = 0;
    virtual LONG get_virtualBasePointerOffset() = 0;
    virtual CSymbolPtr get_virtualTableShape() = 0;
    virtual bool get_code() = 0;
    virtual bool get_function() = 0;
    virtual bool get_managed() = 0;
    virtual bool get_msil() = 0;
    virtual DWORD get_virtualBaseDispIndex() = 0;
    virtual std::wstring get_undecoratedName() = 0;
    virtual DWORD get_age() = 0;
    virtual DWORD get_signature() = 0;
    virtual bool get_compilerGenerated() = 0;
    virtual bool get_addressTaken() = 0;
    virtual DWORD get_rank() = 0;
    virtual CSymbolPtr get_lowerBound() = 0;
    virtual CSymbolPtr get_upperBound() = 0;
    virtual python::list get_dataBytes() = 0;
    virtual DWORD get_targetSection() = 0;
    virtual DWORD get_targetOffset() = 0;
    virtual DWORD get_targetRelativeVirtualAddress() = 0;
    virtual ULONGLONG get_targetVirtualAddress() = 0;
    virtual DWORD get_machineType() = 0;
    virtual DWORD get_oemId() = 0;
    virtual DWORD get_oemSymbolId() = 0;
    virtual CEnumSymbolsPtr get_types() = 0;
    virtual CSymbolPtr get_objectPointerType() = 0;
    virtual DWORD get_udtKind() = 0;
    virtual bool get_noReturn() = 0;
    virtual bool get_customCallingConvention() = 0;
    virtual bool get_noInline() = 0;
    virtual bool get_optimizedCodeDebugInfo() = 0;
    virtual bool get_notReached() = 0;
    virtual bool get_interruptReturn() = 0;
    virtual bool get_farReturn() = 0;
    virtual bool get_isStatic() = 0;
    virtual bool get_hasDebugInfo() = 0;
    virtual bool get_isLTCG() = 0;
    virtual bool get_isDataAligned() = 0;
    virtual bool get_hasSecurityChecks() = 0;
    virtual std::wstring get_compilerName() = 0;
    virtual bool get_hasAlloca() = 0;
    virtual bool get_hasSetJump() = 0;
    virtual bool get_hasLongJump() = 0;
    virtual bool get_hasInlAsm() = 0;
    virtual bool get_hasEH() = 0;
    virtual bool get_hasSEH() = 0;
    virtual bool get_hasEHa() = 0;
    virtual bool get_isNaked() = 0;
    virtual bool get_isAggregated() = 0;
    virtual bool get_isSplitted() = 0;
    virtual CSymbolPtr get_container() = 0;
    virtual bool get_inlSpec() = 0;
    virtual bool get_noStackOrdering() = 0;
    virtual CSymbolPtr get_virtualBaseTableType() = 0;
    virtual bool get_hasManagedCode() = 0;
    virtual bool get_isHotpatchable() = 0;
    virtual bool get_isCVTCIL() = 0;
    virtual bool get_isMSILNetmodule() = 0;
    virtual bool get_isCTypes() = 0;
    virtual bool get_isStripped() = 0;
};

// ----------------------------------------------------------------------------

template< class DiaSymbolT >
class CSymbolImpl : public ISymbol
{
    typedef _com_IIID< DiaSymbolT, &__uuidof(DiaSymbolT) > CIiid;
    typedef _com_ptr_t< CIiid > CImplPtr;

public:
    explicit CSymbolImpl(const CImplPtr &pSymbol)
        : m_pSymbol(pSymbol)
    {
    }

    virtual CEnumSymbolsPtr findChildren(
        DWORD symtag,
        std::wstring name,
        DWORD compareFlags
    ) override
    {
        return 
            findChildrenT(
                &DiaSymbolT::findChildren,
                "IDiaSymbol::findChildren",
                symtag,
                name,
                compareFlags);
    }

#define _diabind_SYMBOL_IMPL_PARAM2RET(type, name)                                    \
    virtual type name() override                                                    \
    {                                                                               \
        return CallMethodOutParamToRet(&DiaSymbolT::##name, "IDiaSymbol::" #name);  \
    }

#define _diabind_SYMBOL_IMPL_NEWSYMBOL(name)                                          \
    virtual CSymbolPtr name() override                                              \
    {                                                                               \
        return CallMethodOutCreateSymbol(&DiaSymbolT::##name, "IDiaSymbol::" #name);\
    }

#define _diabind_SYMBOL_IMPL_BSTR(name)                                               \
    virtual std::wstring name() override                                            \
    {                                                                               \
        return CallMethodOutBstrToRet(&DiaSymbolT::##name, "IDiaSymbol::" #name);   \
    }

#define _diabind_SYMBOL_IMPL_BOOL(name)                                               \
    virtual bool name() override                                                    \
    {                                                                               \
        return !!CallMethodOutParamToRet(&DiaSymbolT::##name, "IDiaSymbol::" #name);\
    }

    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_symTag)
    _diabind_SYMBOL_IMPL_BSTR(get_name)
    virtual std::wstring get_undecoratedNameEx(
        DWORD undecorateOptions
    ) override
    {
        _bstr_t bstrName;
        HRESULT hResult = 
            m_pSymbol->get_undecoratedNameEx(undecorateOptions, bstrName.GetAddress());
        if (S_OK != hResult)
            throw CException(hResult, "IDiaSymbol::get_undecoratedNameEx");

        return std::wstring(bstrName);
    }
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_symIndexId)
    _diabind_SYMBOL_IMPL_NEWSYMBOL(get_lexicalParent)
    _diabind_SYMBOL_IMPL_NEWSYMBOL(get_classParent)
    _diabind_SYMBOL_IMPL_NEWSYMBOL(get_type)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_dataKind)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_locationType)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_addressSection)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_addressOffset)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_relativeVirtualAddress)
    _diabind_SYMBOL_IMPL_PARAM2RET(ULONGLONG, get_virtualAddress)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_registerId)
    _diabind_SYMBOL_IMPL_PARAM2RET(LONG, get_offset)
    _diabind_SYMBOL_IMPL_PARAM2RET(ULONGLONG, get_length)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_slot)
    _diabind_SYMBOL_IMPL_BOOL(get_volatileType)
    _diabind_SYMBOL_IMPL_BOOL(get_constType)
    _diabind_SYMBOL_IMPL_BOOL(get_unalignedType)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_access)
    _diabind_SYMBOL_IMPL_BSTR(get_libraryName)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_platform)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_language)
    _diabind_SYMBOL_IMPL_BOOL(get_editAndContinueEnabled)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_frontEndMajor)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_frontEndMinor)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_frontEndBuild)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_backEndMajor)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_backEndMinor)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_backEndBuild)
    _diabind_SYMBOL_IMPL_BSTR(get_sourceFileName)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_thunkOrdinal)
    _diabind_SYMBOL_IMPL_PARAM2RET(LONG, get_thisAdjust)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_virtualBaseOffset)
    _diabind_SYMBOL_IMPL_BOOL(get_virtual)
    _diabind_SYMBOL_IMPL_BOOL(get_intro)
    _diabind_SYMBOL_IMPL_BOOL(get_pure)
    virtual python::object get_value() override
    {
        _variant_t Variant;
        HRESULT hResult = m_pSymbol->get_value(&Variant);
        if (S_OK != hResult)
            throw CException(hResult, "IDiaSymbol::get_value");
        switch (Variant.vt)
        {
        case VT_I1:
            return python::object(static_cast<LONG>(Variant.bVal));

        case VT_UI1:
            return python::object(static_cast<ULONG>(Variant.bVal));

        case VT_BOOL:
            return python::object(!!Variant.iVal);

        case VT_I2:
            return python::object(static_cast<LONG>(Variant.iVal));

        case VT_UI2:
            return python::object(static_cast<ULONG>(Variant.iVal));

        case VT_I4:
        case VT_INT:
            return python::object(static_cast<LONG>(Variant.lVal));

        case VT_UI4:
        case VT_UINT:
        case VT_ERROR:
        case VT_HRESULT:
            return python::object(static_cast<ULONG>(Variant.lVal));

        case VT_I8:
            return python::object(static_cast<LONG64>(Variant.llVal));

        case VT_UI8:
            return python::object(static_cast<ULONG64>(Variant.llVal));
        }
        throw CPyException( PyExc_ValueError, "Unsupported VARIANT type" );
    }
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_callingConvention)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_baseType)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_token)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_timeStamp)
    virtual std::wstring get_guid() override
    {
        GUID RetVal;
        HRESULT hResult = m_pSymbol->get_guid(&RetVal);
        if (S_OK != hResult)
            throw CException(hResult, "IDiaSymbol::get_guid");

        class CUuidString : protected boost::noncopyable
        {
        public:
            CUuidString() : m_p(NULL) {}
            ~CUuidString()
            {
                if (m_p)
                    ::RpcStringFree(&m_p);
            }

            TCHAR *Get() const { return reinterpret_cast<TCHAR *>(m_p); }
            RPC_WSTR *GetAddress() { return &m_p; }

        private:
            RPC_WSTR m_p;
        } UuidString;
        RPC_STATUS Status = ::UuidToString(&RetVal, UuidString.GetAddress());
        if (RPC_S_OK != Status)
            throw CException(Status, "::UuidToString");

        return std::wstring( UuidString.Get() );
    }
    _diabind_SYMBOL_IMPL_BSTR(get_symbolsFileName)
    _diabind_SYMBOL_IMPL_BOOL(get_reference)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_count)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_bitPosition)
    _diabind_SYMBOL_IMPL_NEWSYMBOL(get_arrayIndexType)
    _diabind_SYMBOL_IMPL_BOOL(get_packed)
    _diabind_SYMBOL_IMPL_BOOL(get_constructor)
    _diabind_SYMBOL_IMPL_BOOL(get_overloadedOperator)
    _diabind_SYMBOL_IMPL_BOOL(get_nested)
    _diabind_SYMBOL_IMPL_BOOL(get_hasNestedTypes)
    _diabind_SYMBOL_IMPL_BOOL(get_hasAssignmentOperator)
    _diabind_SYMBOL_IMPL_BOOL(get_hasCastOperator)
    _diabind_SYMBOL_IMPL_BOOL(get_scoped)
    _diabind_SYMBOL_IMPL_BOOL(get_virtualBaseClass)
    _diabind_SYMBOL_IMPL_BOOL(get_indirectVirtualBaseClass)
    _diabind_SYMBOL_IMPL_PARAM2RET(LONG, get_virtualBasePointerOffset)
    _diabind_SYMBOL_IMPL_NEWSYMBOL(get_virtualTableShape)
    _diabind_SYMBOL_IMPL_BOOL(get_code)
    _diabind_SYMBOL_IMPL_BOOL(get_function)
    _diabind_SYMBOL_IMPL_BOOL(get_managed)
    _diabind_SYMBOL_IMPL_BOOL(get_msil)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_virtualBaseDispIndex)
    _diabind_SYMBOL_IMPL_BSTR(get_undecoratedName)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_age)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_signature)
    _diabind_SYMBOL_IMPL_BOOL(get_compilerGenerated)
    _diabind_SYMBOL_IMPL_BOOL(get_addressTaken)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_rank)
    _diabind_SYMBOL_IMPL_NEWSYMBOL(get_lowerBound)
    _diabind_SYMBOL_IMPL_NEWSYMBOL(get_upperBound)
    virtual python::list get_dataBytes() override
    {
        DWORD cbData = 0;
        HRESULT hResult = m_pSymbol->get_dataBytes(cbData, &cbData, NULL);
        if (S_OK != hResult)
            throw CException(hResult, "IDiaSymbol::get_dataBytes");

        if (!cbData)
            return python::list();

        std::vector< UCHAR > bufBytes(cbData);
        hResult = m_pSymbol->get_dataBytes(cbData, &cbData, &bufBytes[0]);
        if (S_OK != hResult)
            throw CException(hResult, "IDiaSymbol::get_dataBytes");

        python::list lstBytes;
        std::vector< UCHAR >::const_iterator itByte = bufBytes.cbegin();
        for (; itByte != bufBytes.cend(); ++itByte)
            lstBytes.append(*itByte);

        return lstBytes;
    }
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_targetSection)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_targetOffset)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_targetRelativeVirtualAddress)
    _diabind_SYMBOL_IMPL_PARAM2RET(ULONGLONG, get_targetVirtualAddress)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_machineType)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_oemId)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_oemSymbolId)
    virtual CEnumSymbolsPtr get_types() override
    {
        DWORD cbData = 0;
        HRESULT hResult = m_pSymbol->get_types(cbData, &cbData, NULL);
        if (S_OK != hResult)
            throw CException(hResult, "IDiaSymbol::get_types");

        typedef CEnumSymbolsFromVector<DiaSymbolT> CEnumSymbols;
        std::vector<CEnumSymbols::CImplPtr> arrTypes(cbData);

        if (cbData)
        {
            std::vector< DiaSymbolT * > arrTypesRaw(cbData);
            HRESULT hResult = m_pSymbol->get_types(cbData, &cbData, &arrTypesRaw[0]);
            if (S_OK != hResult)
                throw CException(hResult, "IDiaSymbol::get_types");

            for (size_t i = 0; i < arrTypes.size(); ++i)
                arrTypes[i].Attach(arrTypesRaw[i]);
        }

        return CEnumSymbolsPtr( new CEnumSymbols(arrTypes) );

    }
    _diabind_SYMBOL_IMPL_NEWSYMBOL(get_objectPointerType)
    _diabind_SYMBOL_IMPL_PARAM2RET(DWORD, get_udtKind)
    _diabind_SYMBOL_IMPL_BOOL(get_noReturn)
    _diabind_SYMBOL_IMPL_BOOL(get_customCallingConvention)
    _diabind_SYMBOL_IMPL_BOOL(get_noInline)
    _diabind_SYMBOL_IMPL_BOOL(get_optimizedCodeDebugInfo)
    _diabind_SYMBOL_IMPL_BOOL(get_notReached)
    _diabind_SYMBOL_IMPL_BOOL(get_interruptReturn)
    _diabind_SYMBOL_IMPL_BOOL(get_farReturn)
    _diabind_SYMBOL_IMPL_BOOL(get_isStatic)
    _diabind_SYMBOL_IMPL_BOOL(get_hasDebugInfo)
    _diabind_SYMBOL_IMPL_BOOL(get_isLTCG)
    _diabind_SYMBOL_IMPL_BOOL(get_isDataAligned)
    _diabind_SYMBOL_IMPL_BOOL(get_hasSecurityChecks)
    _diabind_SYMBOL_IMPL_BSTR(get_compilerName)
    _diabind_SYMBOL_IMPL_BOOL(get_hasAlloca)
    _diabind_SYMBOL_IMPL_BOOL(get_hasSetJump)
    _diabind_SYMBOL_IMPL_BOOL(get_hasLongJump)
    _diabind_SYMBOL_IMPL_BOOL(get_hasInlAsm)
    _diabind_SYMBOL_IMPL_BOOL(get_hasEH)
    _diabind_SYMBOL_IMPL_BOOL(get_hasSEH)
    _diabind_SYMBOL_IMPL_BOOL(get_hasEHa)
    _diabind_SYMBOL_IMPL_BOOL(get_isNaked)
    _diabind_SYMBOL_IMPL_BOOL(get_isAggregated)
    _diabind_SYMBOL_IMPL_BOOL(get_isSplitted)
    _diabind_SYMBOL_IMPL_NEWSYMBOL(get_container)
    _diabind_SYMBOL_IMPL_BOOL(get_inlSpec)
    _diabind_SYMBOL_IMPL_BOOL(get_noStackOrdering)
    _diabind_SYMBOL_IMPL_NEWSYMBOL(get_virtualBaseTableType)
    _diabind_SYMBOL_IMPL_BOOL(get_hasManagedCode)
    _diabind_SYMBOL_IMPL_BOOL(get_isHotpatchable)
    _diabind_SYMBOL_IMPL_BOOL(get_isCVTCIL)
    _diabind_SYMBOL_IMPL_BOOL(get_isMSILNetmodule)
    _diabind_SYMBOL_IMPL_BOOL(get_isCTypes)
    _diabind_SYMBOL_IMPL_BOOL(get_isStripped)

protected:
    template< class DiaEnumSymbolsT, typename SymTagEnumT >
    CEnumSymbolsPtr findChildrenT(
        HRESULT (STDMETHODCALLTYPE DiaSymbolT::*pMethod)(SymTagEnumT, LPCOLESTR, DWORD, DiaEnumSymbolsT **),
        const char *szMethodName,
        DWORD symtag,
        std::wstring name,
        DWORD compareFlags
    )
    {
        _com_ptr_t< _com_IIID<DiaEnumSymbolsT, &__uuidof(DiaEnumSymbolsT)> > pEnumSymbols;
        HRESULT hResult = 
            (m_pSymbol->*pMethod)(
                static_cast<SymTagEnumT>(symtag),
                name.empty() ? NULL : name.c_str(),
                compareFlags,
                &pEnumSymbols);
        if (S_OK != hResult)
            throw CException(hResult, szMethodName);

        return CEnumSymbolsPtr( new CEnumSymbolsImpl<DiaEnumSymbolsT>(pEnumSymbols) );
    }

    template< typename ArgT >
    ArgT CallMethodOutParamToRet(
        HRESULT (STDMETHODCALLTYPE DiaSymbolT::*pMethod)(ArgT *),
        const char *szMethodName
    )
    {
        ArgT RetVal;
        HRESULT hResult = (m_pSymbol->*pMethod)(&RetVal);
        if (S_OK != hResult)
            throw CException(hResult, szMethodName);
        return RetVal;
    }

    CSymbolPtr CallMethodOutCreateSymbol(
        HRESULT (STDMETHODCALLTYPE DiaSymbolT::*pMethod)(DiaSymbolT **),
        const char *szMethodName
    )
    {
        _com_ptr_t< _com_IIID<DiaSymbolT, &__uuidof(DiaSymbolT)> > pSymbol;
        HRESULT hResult = (m_pSymbol->*pMethod)(&pSymbol);
        if (S_OK != hResult)
            throw CException(hResult, szMethodName);
        return CSymbolPtr( new CSymbolImpl<DiaSymbolT>(pSymbol) );
    }

    std::wstring CallMethodOutBstrToRet(
        HRESULT (STDMETHODCALLTYPE DiaSymbolT::*pMethod)(BSTR *),
        const char *szMethodName
    )
    {
        _bstr_t bstrValue;
        HRESULT hResult = (m_pSymbol->*pMethod)(bstrValue.GetAddress());
        if (S_OK != hResult)
            throw CException(hResult, szMethodName);
        return std::wstring(bstrValue);
    }

private:
    CImplPtr m_pSymbol;
};

// ----------------------------------------------------------------------------

}   // namespace diabind

// ----------------------------------------------------------------------------

